<template>
  <!--
      使用方式
      变量  modelValue:  编辑时使用的默认值 新增可以不传
            contentHeight: 默认高度 不传为200
            placeholder: 占位符 提示文字
      方法  changeVal(val){ 修改父组件变量为参数 val 实时更新 }
      <TextEditor :default-val="'123'" @changeVal="val=>textEditor=val" />
  -->
  <div ref="wangEditor" class="com-editor" />
</template>
<script>
// 富文本
import Wangeditor from 'wangeditor'
import hljs from 'highlight.js'
import 'highlight.js/styles/monokai-sublime.css'
import ObsClient from "esdk-obs-browserjs";
import { FileUploadMenu } from "./fileUploadBtn";
import { Paperclip } from "@element-plus/icons-vue";
export default {
  props: {
    modelValue: {
      type: String,
      default: '',
    },
    placeholder: {
      type: String,
      default: '请输入',
    },
    contentHeight: {
      type: Number,
      default: 200,
    },
    noCode: {
      type: Boolean,
      default: false,
    },
  },
  data () {
    return {
      editor: null,
      contentHeightH: '',
      // 上传图片相关的property
      defaultUploadFiles: [],
      access_key_id: '43I9JLFQGK4HTIVS4HHJ',
      secret_access_key: 'Y0CfSExq0PmgokPwvu415kg6S5vEBWfeZRhaqMhq',
      bucketName: 'neuedu-expo-test', // 桶名
      serverUrl: 'https://obs.cn-north-4.myhuaweicloud.com', // 服务器地址
      server: 'obs.cn-north-4.myhuaweicloud.com',
      obsClient: null
    }
  },
  mounted () {
    this.contentHeightH =
      (this.contentHeight > 150 ? this.contentHeight : 150) + 'px'
    this.initEditor()
  },
  beforeDestroy () {
    // 销毁编辑器
    this.editor.destroy()
    this.editor = null
  },
  methods: {
    timestampToTime () {
      var date = new Date() //时间戳为10位需*1000，时间戳为13位的话不需乘1000
      var Y = date.getFullYear() + '/'
      var M =
        (date.getMonth() + 1 < 10
          ? '0' + (date.getMonth() + 1)
          : date.getMonth() + 1) + '/'
      var D =
        (date.getDate() < 10 ? '0' + date.getDate() : date.getDate()) + '/'
      return Y + M + D
    },
    timestampTime () {
      var date = new Date() //时间戳为10位需*1000，时间戳为13位的话不需乘1000
      var Y = date.getFullYear()
      var M =
        date.getMonth() + 1 < 10
          ? '0' + (date.getMonth() + 1)
          : date.getMonth() + 1
      var D = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
      var h = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
      var m =
        date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
      var s =
        date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
      return Y + M + D + h + m + s
    },
    handleFileChange (e) {
      const file = e.files[0]
      var date = new Date()
      // 取文件名
      const n = file.name.lastIndexOf(".")
      const fileName = file.name.substr(0, n)
      // 文件后缀
      const type = file.name.substr(n + 1, file.name.length)
      const timestampFileName =
        this.timestampToTime(date) +
        fileName +
        '_' +
        this.timestampTime(date) +
        '.' +
        type

      this.obsClient.putObject(
        {
          Bucket: this.bucketName, // 桶名
          Key: timestampFileName, // 文件名
          SourceFile: file,
          ContentType: 'text/plain',
        },
        (err, result) => {
          if (err) {
            this.$message.error({
              message: '上传失败，请重试',
            })
          } else {
            if (result.CommonMsg.Status < 300) {
              // 上传成功后，文件地址
              const fileUrl =
                'https://' +
                this.bucketName +
                '.' +
                this.server +
                '/' +
                timestampFileName
              this.editor.txt.append(`<footer><p><a href="${fileUrl}">${file.name}</a></p></footer>`)
            } else {
              this.$message.error({
                message: '上传失败，请重试',
              })
            }
          }
        }
      )
    },
    initEditor () {
      let that = this

      window.handleFileChange = this.handleFileChange;
      // huawei OBS Client
      this.obsClient = new ObsClient({
        access_key_id: this.access_key_id,
        secret_access_key: this.secret_access_key,
        server: this.serverUrl,
      })

      const menuKey = 'fileUploadMenuKey'

      Wangeditor.registerMenu(menuKey, FileUploadMenu)

      this.$nextTick(() => {
        // 初始化
        this.editor = new Wangeditor(this.$refs.wangEditor)
        // 高度
        this.editor.config.height = 100
        this.editor.config.uploadImgShowBase64 = true
        // 挂载highlight插件
        this.editor.highlight = hljs
        // 不自动获取焦点  循环调用时 获取焦点会报错 warning: addRange(): The given range isn't in document.
        this.editor.config.focus = false
        // 关闭全屏功能
        this.editor.config.showFullScreen = false
        // 关闭网络图片链接功能
        this.editor.config.showLinkImg = false
        // 限制图片大小 1m
        this.editor.config.uploadImgMaxSize = 5 * 1024 * 1024
        // 单次最多上传1张
        this.editor.config.uploadImgMaxLength = 1
        // 提示文字
        this.editor.config.placeholder = this.placeholder
        // 菜单配置
        this.editor.config.menus = [
          'head',
          'bold',
          'italic',
          'underline',
          'strikeThrough',
          'fontSize',
          'fontName',
          'indent',
          'lineHeight',
          'foreColor',
          'backColor',
          // 'link',
          'list',
          // 'todo',
          'justify',
          'quote',
          // 'emoticon',
          'image',
          // 'video',
          // 'table',
          // this.noCode ? '' : 'code',
          // 'splitLine',
          // 'undo',
          // 'redo',
        ]
        this.editor.config.menus.concat(menuKey)
        this.editor.config.menus.concat('splitLine')
        // 字体型号配置
        this.editor.config.fontSizes = {
          'x-small': { name: '12px', value: '1' },
          small: { name: '14px', value: '2' },
          normal: { name: '16px', value: '3' },
          large: { name: '18px', value: '4' },
        }
        // 监听变更事件
        this.editor.config.onchange = (newHtml) => {
          // that.$emit('changeVal', newHtml, this.editor.txt.text())
          that.$emit('update:modelValue', newHtml)//  v-model 不好用，原因未知
        }
        // 自定义的上传图片（华为OBS）
        this.editor.config.customUploadImg = (resultFiles, insertImgFn) => {
          const file = resultFiles[0]
          var date = new Date()
          // 取文件名
          const n = file.name.lastIndexOf(".")
          const fileName = file.name.substr(0, n)
          // 文件后缀
          const type = file.name.substr(n + 1, file.name.length)
          const timestampFileName =
            this.timestampToTime(date) +
            fileName +
            '_' +
            this.timestampTime(date) +
            '.' +
            type

          this.obsClient.putObject(
            {
              Bucket: this.bucketName, // 桶名
              Key: timestampFileName, // 文件名
              SourceFile: file,
              ContentType: 'text/plain',
            },
            (err, result) => {
              if (err) {
                this.$message.error({
                  message: '上传失败，请重试',
                })
              } else {
                if (result.CommonMsg.Status < 300) {
                  // 上传成功后，文件地址
                  const fileUrl =
                    'https://' +
                    this.bucketName +
                    '.' +
                    this.server +
                    '/' +
                    timestampFileName
                  insertImgFn(fileUrl)
                } else {
                  this.$message.error({
                    message: '上传失败，请重试',
                  })
                }
              }
            }
          )
        }
        this.editor.config.uploadImgMaxLength = 1
        this.editor.create()
        // 设置默认值
        let _html = this.modelValue || ''
        this.editor.txt.html(_html)
      })
    },
  },
}
</script>
<style lang="scss" scoped>
.com-editor {
  position: relative;
  line-height: 22px;
  max-width: 720px;

  :deep(.w-e-text-container) {
    height: auto !important;
    border-radius: 0 0 4px 4px;
  }

  :deep(.w-e-text) {
    min-height: v-bind(contentHeightH) !important;
  }

  :deep(.w-e-toolbar) {
    border-radius: 4px 4px 0 0;
  }
}

.w-e-icon-play:before {
  content: '';
}
</style>
